package com.imitationsql.web.tree;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>Description: 树工具类 </p>
 *
 * @author : xiaodong.yang
 * @date : 2024/4/8 15:57
 */
public class TreeUtil {


    /**
     * 计算深度
     *
     * @param list
     * @param <T>
     * @return
     */
    public <T extends ClosureTable> void computeDepth(List<T> list) {
        listToTree(list);
    }


    /**
     * list转成tree结构
     *
     * @param list
     * @param <T>
     * @return
     */
    public <T extends ClosureTable> List<T> listToTree(List<T> list) {
        List<T> dataList = new ArrayList<>();
        if (CollUtil.isEmpty(list)) {
            return dataList;
        }
        //没有父类的数据
        list.stream().filter(item -> StrUtil.isEmpty(item.getParentId())).forEach(item -> item.setDepth(0));
        //有父类的数据
        List<T> existParentList = list.stream().filter(item -> StrUtil.isNotBlank(item.getParentId())).collect(Collectors.toList());
        Map<String, List<T>> map = existParentList.stream().collect(Collectors.groupingBy(ClosureTable::getParentId));
        for (T item : existParentList) {
            item.setChildren(getChildren(map, item, 0));
            dataList.add(item);
        }
        return dataList;
    }

    /**
     * 树形结构转list
     *
     * @param list
     * @param <T>
     * @return
     */
    public <T extends ClosureTable> List<T> treeToList(List<T> list) {
        List<T> dataList = new ArrayList<>();
        if (CollUtil.isEmpty(list)) {
            return dataList;
        }
        for (T t : list) {
            dataList.add(t);
            getChildren(t, dataList);
        }
        return dataList;
    }

    private <T extends ClosureTable> void getChildren(T item, List<T> dataList) {
        List<? extends ClosureTable> children = item.getChildren();
        if (CollUtil.isNotEmpty(children)) {
            for (ClosureTable child : children) {
                dataList.add((T) child);
                getChildren((T) child, dataList);
            }
        }
    }

    /**
     * 计算子类深度
     *
     * @param map
     * @param t
     * @param depth
     * @param <T>
     */
    private <T extends ClosureTable> List<T> getChildren(Map<String, List<T>> map, T t, int depth) {
        List<T> children = map.get(t.getParentId());
        List<T> dataList = new ArrayList<>();
        if (CollUtil.isEmpty(children)) {
            t.setDepth(depth);
            return dataList;
        }
        for (T child : children) {
            depth++;
            child.setChildren(getChildren(map, child, depth));
            dataList.add(child);
        }
        return dataList;
    }
}
